﻿using Microsoft.AspNetCore.Mvc;
using PmSoft.Core;
using PmSoft.Web.Abstractions;
using PmSoft.Web.Abstractions.Attachment;
using PmSoft.Web.Abstractions.Services;
using System.Text.RegularExpressions;

namespace Demo.PetaPoco.WebApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class FileController(IFileUploadService uploadService, AttachmentManagerService attachmentManagerService) : ControllerBase
{
	/// <summary>
	/// 普通上传
	/// </summary>
	/// <param name="file"></param>
	/// <returns></returns>
	[HttpPost("upload")]
	public async Task<IApiResult> UploadFile(IFormFile file)
	{
		try
		{
			var fileName = await uploadService.UploadFileAsync(file, "uploads", "test.jpg", Path.Combine("files", "test"));
			return ApiResult.Ok(new { fileName });
		}
		catch (Exception ex)
		{
			return ApiResult.Error(ex.Message);

		}
	}

	/// <summary>
	/// 分片上传
	/// </summary>
	/// <param name="file"></param>
	/// <param name="fileName"></param>
	/// <param name="chunkNumber"></param>
	/// <param name="totalChunks"></param>
	/// <returns></returns>
	[HttpPost("upload-chunk")]
	public async Task<IActionResult> UploadChunk(
		IFormFile file,
		[FromQuery] string fileName,
		[FromQuery] int chunkNumber,
		[FromQuery] int totalChunks)
	{
		try
		{
			var result = await uploadService.UploadChunkAsync(file, fileName, chunkNumber, totalChunks, "uploads");
			if (result.IsCompleted)
				return Ok($"文件 {fileName} 分片上传完成并合并成功。");
			return Ok($"分片 {chunkNumber}/{totalChunks} 上传成功。");
		}
		catch (ArgumentException ex)
		{
			return BadRequest(ex.Message);
		}
	}

	/// <summary>
	/// 测试上传临时附件的 Web API 方法（普通文件上传）
	/// </summary>
	/// <param name="file">上传的文件</param>
	/// <param name="tenantType">租户类型，例如 "Company" 或 "User"</param>
	/// <returns>上传结果，包含附件ID或错误信息</returns>
	[HttpPost("upload-temporary")]
	public async Task<IActionResult> UploadTemporaryAttachmentAsync(IFormFile file, [FromQuery] string tenantType)
	{
		// 检查输入参数
		if (file == null || file.Length == 0)
			throw new PmSoftException("未提供有效的文件。");
		if (string.IsNullOrEmpty(tenantType))
			throw new PmSoftException("租户类型未指定。");


		// 调用附件管理服务的普通上传方法
		var attachment = await attachmentManagerService.UploadTemporaryAttachmentAsync(file, tenantType);

		// 返回成功结果
		return Ok(new
		{
			attachment.AttachmentId,
			attachment.FileName,
			attachment.FriendlyName,
			attachment.ObjectName,
			attachment.BucketName,
			MediaType = attachment.MediaType.ToString(),
			attachment.MimeType,
			attachment.FileSize,
			attachment.UploaderIp,
			attachment.Description,
			attachment.IsTemporary,
			Message = "临时附件上传成功。"
		});
	}
	/// <summary> 
	/// 上传临时附件的 Web API 方法（文件流上传）
	/// </summary>
	/// <param name="file">上传的文件</param>
	/// <param name="tenantType">租户类型，例如 "Company" 或 "User"</param>
	/// <returns>上传结果，包含附件ID或错误信息</returns>
	[HttpPost("upload-temporary-byte")]
	public async Task<IAttachment?> UploadTemporaryAttachmentByteAsync()
	{
		// 读取请求体中的字节数组
		using var memoryStream = new MemoryStream();
		await Request.Body.CopyToAsync(memoryStream);
		var fileBytes = memoryStream.ToArray();

		if (fileBytes == null || fileBytes.Length == 0)
			throw new ArgumentNullException(nameof(fileBytes), "文件数据不能为空。");

		// 从请求头中获取元数据
		var fileName = Request.Headers["FileName"].ToString();
		var className = Request.Headers["ClassName"].ToString();
		var processType = Request.Headers["ProcessType"].ToString();

		if (string.IsNullOrEmpty(className))
			throw new PmSoftException("租户类型未指定。");

		// 处理缩略图
		if (!string.IsNullOrEmpty(processType) && processType == "is_compress")
		{
			// 缩略图处理
		}

		// 调用附件管理服务的普通上传方法
		var attachment = await attachmentManagerService.UploadTemporaryAttachmentAsync(fileBytes, fileName, className);
		return attachment;
	}
	/// <summary>
	/// 发布临时附件为正式附件的 Web API 方法
	/// </summary>
	/// <param name="attachmentId">附件ID，用于标识要发布的附件</param>
	/// <param name="tenantId">租户ID，用于关联具体租户</param>
	/// <param name="friendlyName">友好名称，可选，默认为上传时的原始文件名</param>
	/// <returns>发布结果，包含附件ID或错误信息</returns>
	[HttpPost("publish")]
	public async Task<IActionResult> PublishAttachmentAsync(
		[FromQuery] string attachmentId,
		[FromQuery] string tenantId,
		[FromQuery] string? friendlyName = null)
	{

		// 检查输入参数
		if (string.IsNullOrEmpty(attachmentId))
			throw new PmSoftException("附件ID无效。");
		if (string.IsNullOrEmpty(tenantId))
			throw new PmSoftException("租户ID未指定。");

		// 调用附件管理服务的发布方法
		var attachment = await attachmentManagerService.PublishAttachmentAsync(attachmentId, tenantId, friendlyName);

		// 返回成功结果
		return Ok(new
		{
			attachment.AttachmentId,
			attachment.TenantType,
			attachment.TenantId,
			attachment.FileName,
			attachment.FriendlyName,
			attachment.ObjectName,
			attachment.BucketName,
			MediaType = attachment.MediaType.ToString(),
			attachment.MimeType,
			attachment.FileSize,
			attachment.UploaderIp,
			attachment.Description,
			attachment.IsTemporary,
			Message = "附件已发布为正式文件。"
		});

	}

	/// <summary>
	/// 根据附件ID获取附件信息及文件流的 Web API 方法
	/// </summary>
	/// <param name="attachmentId">附件ID</param>
	/// <returns>附件信息和文件流，或错误信息</returns>
	[HttpGet("{attachmentId}")]
	public async Task<IActionResult> GetAttachment(string attachmentId)
	{
		if (string.IsNullOrEmpty(attachmentId))
			PmSoftException.Throw("附件ID无效。");

		var attachmentWithContent = await attachmentManagerService.GetAttachmentByIdAsync(attachmentId);
		if (attachmentWithContent == null)
			return NotFound("未找到指定的附件。");

		// 返回文件流和附件信息
		return File(attachmentWithContent.Content, attachmentWithContent.Attachment.MimeType,
			attachmentWithContent.Attachment.FriendlyName);
	}

	/// <summary>
	/// 从htm提取附件集合
	/// </summary>
	/// <param name="htmlContent"></param>
	/// <returns></returns>
	public static List<string> ExtractAttachmentIds(string htmlContent)
	{
		// 正则表达式匹配 /api/file/ 后面的 attachmentId
		string pattern = @"/api/file/([^/?\s""]+)";
		var regex = new Regex(pattern);

		// 使用 HashSet 去重
		var attachmentIds = new HashSet<string>();

		// 获取所有匹配项
		MatchCollection matches = regex.Matches(htmlContent);
		foreach (Match match in matches)
		{
			if (match.Success && match.Groups.Count > 1)
			{
				attachmentIds.Add(match.Groups[1].Value);
			}
		}

		return attachmentIds.ToList();
	}
}
